package com.xs.gis.cover.util;

import lombok.SneakyThrows;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.OverviewPolicy;
import org.geotools.coverage.processing.CoverageProcessor;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.collection.ClippedFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.WKTReader;
import org.opengis.coverage.Coverage;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.FactoryException;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import static com.xs.gis.cover.util.CommonMethod.readFeatureCollection;

/**
 * @description:
 * @author: bo
 * @create: 2025-07-01 16:06
 */
public class ImgUtils {
    public static Coverage readTiff(String tiffPath) throws IOException {
        File f = new File(tiffPath);
        ParameterValue<OverviewPolicy> policy = AbstractGridFormat.OVERVIEW_POLICY.createValue();
        policy.setValue(OverviewPolicy.IGNORE);
        ParameterValue<String> gridsize = AbstractGridFormat.SUGGESTED_TILE_SIZE.createValue();
        ParameterValue<Boolean> useJaiRead = AbstractGridFormat.USE_JAI_IMAGEREAD.createValue();
        useJaiRead.setValue(true);
        GridCoverage2D image = new GeoTiffReader(f).read(new GeneralParameterValue[]{policy, gridsize, useJaiRead});
        return image;
    }

    // - 通过掩膜提取
    private static Coverage clipImageToFeatureSource() throws IOException, FactoryException, MismatchedDimensionException {
        SimpleFeatureCollection collection = readFeatureCollection("E:\\data\\shp\\mask.shp");
        FeatureIterator<SimpleFeature> iterator = collection.features();
        List<Geometry> all = new ArrayList<Geometry>();
        try {
            while (iterator.hasNext()) {
                SimpleFeature feature = iterator.next();
                Geometry geometry = (Geometry) feature.getDefaultGeometry();
                all.add(geometry);
            }
        } finally {
            if (iterator != null) {
                iterator.close();
            }
        }
        Coverage coverage = readTiff("");
        Coverage clippedCoverage = null;
        if (all.size() > 0) {
            CoverageProcessor processor = new CoverageProcessor();
            ParameterValueGroup params = processor.getOperation("CoverageCrop")
                    .getParameters();
            params.parameter("Source").setValue(coverage);
            GeometryFactory factory = JTSFactoryFinder.getGeometryFactory(null);
            Geometry[] a = all.toArray(new Geometry[0]);
            GeometryCollection c = new GeometryCollection(a, factory);
            Envelope envelope = all.get(0).getEnvelopeInternal();
            double x1 = envelope.getMinX();
            double y1 = envelope.getMinY();
            double x2 = envelope.getMaxX();
            double y2 = envelope.getMaxY();
            ReferencedEnvelope referencedEnvelope = new ReferencedEnvelope(x1, x2, y1, y2, coverage.getCoordinateReferenceSystem());
            params.parameter("ENVELOPE").setValue(referencedEnvelope);
            params.parameter("ROI").setValue(c);
            params.parameter("ForceMosaic").setValue(true);
            clippedCoverage = processor.doOperation(params);
        }
        if (all.size() == 0) {
            System.out.println("Crop by shapefile requested but no simple features matched extent!");
        }
        return clippedCoverage;
    }

    // - 裁剪
    public static void clip() {
        SimpleFeatureCollection china = readFeatureCollection("E:\\data\\shp\\china.shp");
        SimpleFeatureCollection countries = readFeatureCollection("E:\\data\\shp\\countries.shp");
        SimpleFeature next = china.features().next();
        Geometry geometry = (Geometry) next.getDefaultGeometry();
        ClippedFeatureCollection clippedFeatureCollection = new ClippedFeatureCollection(countries, geometry, true);
        SimpleFeatureIterator clipedFeatures = clippedFeatureCollection.features();
        int gcount = 0;
        while (clipedFeatures.hasNext()) {
            SimpleFeature feature = clipedFeatures.next();
            Collection<Property> properties = feature.getProperties();
            Iterator<Property> iterator = properties.iterator();
            while (iterator.hasNext()) {
                Property property = iterator.next();
                System.out.println(property.getName() + "  " + property.getValue());
            }
            gcount++;
        }
        System.out.println("裁剪后还剩下的元素！" + gcount);
    }

    // 缓存
    public static void buffer() throws IOException, FactoryException {
        SimpleFeatureCollection cities = readFeatureCollection("E:\\data\\shp\\cities.shp");
        List<SimpleFeature> bufferResult = new ArrayList<>();
        SimpleFeatureIterator iterator = cities.features();
        SimpleFeatureType type = CommonMethod.createType(Polygon.class, "citesBuffer");
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
        while (iterator.hasNext()) {
            SimpleFeature simpleFeature = iterator.next();
            Geometry geometry = (Geometry) simpleFeature.getDefaultGeometry();
            Geometry buffer = geometry.buffer(10);//参数设置
            featureBuilder.add("1");
            featureBuilder.add(buffer);
            SimpleFeature bufferSimpleFeature = featureBuilder.buildFeature(null);
            bufferResult.add(bufferSimpleFeature);
        }
        SimpleFeatureCollection collection = new ListFeatureCollection(type, bufferResult);
        CommonMethod.createShp("E:\\data\\shp\\citiesBuffer.shp", collection);
    }

    // - 合并同类图层
    public static void union() throws IOException {
        SimpleFeatureCollection featureCollectionP1 = readFeatureCollection("E:\\data\\shp\\countries_part1.shp");
        SimpleFeatureCollection featureCollectionP2 = readFeatureCollection("E:\\data\\shp\\countries_part2.shp");
        List<SimpleFeature> features = new ArrayList<>();
        SimpleFeatureIterator iterator1 = featureCollectionP1.features();
        SimpleFeatureIterator iterator2 = featureCollectionP2.features();
        while (iterator1.hasNext()) {
            SimpleFeature simpleFeature = iterator1.next();
            features.add(simpleFeature);
        }
        while (iterator2.hasNext()) {
            SimpleFeature simpleFeature = iterator2.next();
            features.add(simpleFeature);
        }
        SimpleFeatureCollection collection = new ListFeatureCollection(featureCollectionP1.getSchema(), features);
        CommonMethod.createShp("E:\\data\\shp\\countries_union.shp", collection);
    }

    // - 多个多边形合并成一个
    public static void merge() throws IOException {
        SimpleFeatureCollection collection = readFeatureCollection("E:\\data\\shp\\countries_mergedata.shp");
        SimpleFeatureIterator features = collection.features();
        List<Polygon> polygons = new ArrayList<>();
        while (features.hasNext()) {
            SimpleFeature simpleFeature = features.next();
            Geometry defaultGeometry = (Geometry) simpleFeature.getDefaultGeometry();
            Geometry union = defaultGeometry.union();
            polygons.add((Polygon) union);
        }
        Polygon[] ps = polygons.toArray(new Polygon[polygons.size()]);
        MultiPolygon multiPolygon = new MultiPolygon(ps, new GeometryFactory());
        Geometry union = multiPolygon.union();
        SimpleFeatureType type = CommonMethod.createType(MultiPolygon.class, "countriesMerge");
        SimpleFeatureBuilder builder = new SimpleFeatureBuilder(type);
        builder.add("1");
        builder.add(union);
        SimpleFeature simpleFeature = builder.buildFeature(null);
        List<SimpleFeature> featureList = new ArrayList<>();
        featureList.add(simpleFeature);
        SimpleFeatureCollection simpleFeatureCollection = new ListFeatureCollection(type, featureList);
        // 生成矢量数据
        CommonMethod.createShp("E:\\data\\shp\\countriesMerge.shp", simpleFeatureCollection);
    }

    // gp 裁剪
    @SneakyThrows
    public static void clipTest() {
        SimpleFeatureCollection featureCollection = CommonMethod.readFeatureCollection("E:\\data\\bf.shp");
        WKTReader wktReader = new WKTReader();
        Geometry geometry = wktReader.read("MultiPolygon (((120.06170797626219837 30.54693549152121079, 120.12450974119508373 30.54442342092389495, 120.13644207653233309 30.49192114543999921, 120.06723453157628967 30.48878105719335707, 120.06170797626219837 30.54693549152121079)))");
        ClippedFeatureCollection clippedFeatureCollection = new ClippedFeatureCollection(featureCollection, geometry, false);
        CommonMethod.createShp("E:\\data\\clip.shp", clippedFeatureCollection);
    }
}
